#pragma once
#ifndef _LISTSTACK_H
#define _LISTSTACK_H

template<typename T> class ListStack;
template<typename T>
class Node {
	template<typename T> 
	friend class ListStack;

private:
	T val;
	Node* next;
	Node(const T& in) :val(in){
		next = NULL;
	}
	Node() {
		next = NULL;
	}
};

template<typename T> 
class ListStack {

private:
	Node<T>* first;
public:
	ListStack();
	~ListStack();
	bool empty() const;
	const T& top() const;
	void push(const T& tar);
	void pop();

};

template<typename T>
ListStack<T>::ListStack() {
	first = new Node<T>();
}

template<typename T>
ListStack<T>::~ListStack() {
	while (!empty()){
		pop();
	}
	delete first;
}

template<typename T>
bool ListStack<T>::empty() const {
	return first->next == NULL;
}

template<typename T>
const T& ListStack<T>::top() const{
	if (empty()) {
		throw "The stack is empty! No top element.";
	}
	return first->next->val;
}

template<typename T>
void ListStack<T>::push(const T& tar) {
	Node<T>* newnode = new Node<T>(tar);
	newnode->next = first->next;
	first->next = newnode;
}

template<typename T>
void ListStack<T>::pop() {
	if (empty()){
		throw "The stack is empty! Can not pop.";
	}
	Node<T>* tmp=first->next;
	first->next = tmp->next;
	delete tmp;
}

#endif